import { createStore, Commit } from 'vuex'
import axios, { AxiosRequestConfig } from 'axios'
import { ArrToObj, ObjToArr } from './helper'
export interface ImageProps{
  _id?: string;
  url?: string;
  createAt?: string;
}
export interface ResponseType{
  code: number;
  msg: string;
  data: ImageProps;
}
export interface UserProps{
  isLogin: boolean;
  nickName?: string;
  _id?: string;
  column?: string;
  avatar?: ImageProps;
  description?: string;
  email?: string;
}
export interface ColumnProps{
  _id: string;
  title: string;
  // 可选
  avatar?: ImageProps;
  description: string;
}
export interface PostProps{
  _id?: string;
  title: string;
  excerpt?: string;
  content?: string;
  image?: ImageProps | string;
  createdAt?: string;
  column: string;
  author?: string | UserProps;
  isHTML?: boolean;
}
export interface PostResponseType {
  code: number;
  msg: string;
  data: PostProps;
}
interface ListProps<p> {
  [id: string]: p
}
export interface GlobalErrorProps{
  status: boolean;
  message?: string;
}
export interface GlobalDataProps{
  user: UserProps;
  columns: { data: ListProps<ColumnProps>; currentPage: number; total: number };
  post: { data: ListProps<PostProps>; loadedColumns: string[]; currentPage: number; total: number };
  loading: boolean;
  token: string;
  error: GlobalErrorProps;
}
// const getAndCommit = async (url: string, mutations: string, commit: Commit) => {
//   const { data } = await axios.get(url)
//   commit(mutations, data)
//   return data
// }
// eslint-disable-next-line
// const postAndCommit = async (url: string, mutations: string, commit: Commit, payload: any) => {
//   const { data } = await axios.post(url, payload)
//   commit(mutations, data)
//   return data
// }
const asyncAndCommit = async (url: string, mutations: string, commit: Commit, config: AxiosRequestConfig = { method: 'get' }, extraData?: any) => {
  const { data } = await axios(url, config)
  if (extraData) {
    commit(mutations, { data, extraData })
  } else {
    commit(mutations, data)
  }
  return data
}
const store = createStore<GlobalDataProps>({
  state: {
    user: {
      isLogin: false
    },
    columns: { data: {}, currentPage: 0, total: 0 },
    post: { data: {}, loadedColumns: [], currentPage: 0, total: 0 },
    loading: false,
    token: localStorage.getItem('token') || '',
    error: {
      status: false
    }
  },
  mutations: {
    createPost (state, newPost) {
      state.post.data[newPost._id] = newPost
    },
    fetchColumns (state, rawData) {
      const { data } = state.columns
      const { list, count, currentPage } = rawData.data
      state.columns = {
        data: { ...data, ...ArrToObj(list) },
        total: count,
        currentPage: currentPage * 1
      }
    },
    fetchColumn (state, rawData) {
      state.columns.data[rawData.data._id] = rawData.data
    },
    fetchPosts (state, { data: rawData, extraData: columnId }) {
      state.post.data = { ...state.post.data, ...ArrToObj(rawData.data.list) }
      state.post.loadedColumns.push(columnId)
      state.post.total = rawData.data.count
      state.post.currentPage = rawData.data.currentPage
    },
    fetchPost (state, rawData) {
      state.post.data[rawData.data._id] = rawData.data
    },
    updatePost (state, { data }) {
      state.post.data[data._id] = data
    },
    deletePost (state, { data }) {
      delete state.post.data[data._id]
    },
    setLoading (state, status) {
      state.loading = status
    },
    fetchCurrentUser (state, rawData) {
      state.user = { isLogin: true, ...rawData.data }
    },
    login (state, rawData) {
      const { token } = rawData.data
      state.token = token
      localStorage.setItem('token', token)
      axios.defaults.headers.common.Authorization = `Bearer ${token}`
    },
    setError (state, e: GlobalErrorProps) {
      state.error = e
    },
    // 退出登录
    loginOut (state) {
      state.token = ''
      localStorage.removeItem('token')
      delete axios.defaults.headers.common.Authorization
    }
  },
  actions: {
    fetchColumns ({ state, commit }, params = {}) {
      // return getAndCommit('/columns', 'fetchColumns', commit)
      const { currentPage = 1, pageSize = 5 } = params
      if (state.columns.currentPage < currentPage) {
        return asyncAndCommit(`/columns?currentPage=${currentPage}&pageSize=${pageSize}`, 'fetchColumns', commit, {
          method: 'get'
        })
      }
    },
    fetchColumn ({ state, commit }, cid) {
      // return getAndCommit(`/columns/${cid}`, 'fetchColumn', commit)
      if (!state.columns.data[cid]) {
        return asyncAndCommit(`/columns/${cid}`, 'fetchColumn', commit, {
          method: 'get'
        })
      }
    },
    fetchPosts ({ state, commit }, params) {
      // return getAndCommit(`/columns/${cid}/posts`, 'fetchPosts', commit)
      const { currentId, currentPage = 1, pageSize = 5 } = params
      // if (!state.post.loadedColumns.includes(currentId)) {
      return asyncAndCommit(`/columns/${currentId}/posts?currentPage=${currentPage}&pageSize=${pageSize}`, 'fetchPosts', commit, {
        method: 'get'
      }, currentId)
      // }
    },
    // 获取文章详情
    fetchPost ({ state, commit }, cid) {
      // return getAndCommit(`/posts/${cid}`, 'fetchPost', commit)
      const currentPost = state.post.data[cid]
      if (!currentPost || !currentPost.content) {
        return asyncAndCommit(`/posts/${cid}`, 'fetchPost', commit, {
          method: 'get'
        })
      } else {
        return Promise.resolve({ data: currentPost })
      }
    },
    updatePost ({ commit }, { id, payload }) {
      return asyncAndCommit(`/posts/${id}`, 'updatePost', commit, {
        method: 'patch',
        data: payload
      })
    },
    fetchCurrentUser ({ commit }) {
      // return getAndCommit('/user/current', 'fetchCurrentUser', commit)
      return asyncAndCommit('/user/current', 'fetchCurrentUser', commit, {
        method: 'get'
      })
    },
    login ({ commit }, payload) {
      // return postAndCommit('/user/login', 'login', commit, payload)
      return asyncAndCommit('/user/login', 'login', commit, {
        method: 'post',
        data: payload
      })
    },
    createPosts ({ commit }, payload) {
      // return postAndCommit('/posts', 'createPosts', commit, payload)
      return asyncAndCommit('/posts', 'createPosts', commit, {
        method: 'post',
        data: payload
      })
    },
    deletePost ({ commit }, id) {
      return asyncAndCommit(`/posts/${id}`, 'deletePost', commit, {
        method: 'delete'
      })
    },
    async loginAndFetch ({ dispatch }, loginData) {
      return dispatch('login', loginData).then(() => {
        return dispatch('fetchCurrentUser')
      })
    }
  },
  getters: {
    getColumns: (state) => {
      return ObjToArr(state.columns.data)
    },
    getColumnById: (state) => (id: string) => {
      return state.columns.data[id]
    },
    getPostById: (state) => (cid: string) => {
      return ObjToArr(state.post.data).filter((c) => c.column === cid)
    },
    getPostDetailById: (state) => (id: string) => {
      return state.post.data[id]
    }
  }
})

export default store
